#!/bin/sh

. $LKP_SRC/lib/upload.sh

TIMEOUT=3600
ERROR_CODE=100
TIMEOUT_CODE=101

SERVER_IP=${direct_server_ips:-"127.0.0.1"}
CARD_IDS=$test_card_id
CARD_TYPE=$test_card_type
CARD_NAME=$test_card_name
DRIVERLINK=$driverlink

CONFIG_FILE="/usr/share/oech/lib/config/test_config.yaml"
LOGDIR="/usr/share/oech/logs"
SERVER_LOGS="/usr/share/oech/lib/server/results"
REPORT="${CARD_TYPE}-${CARD_NAME}-report.html"

function setup_oech_server() {
    systemctl start oech-server.service
    systemctl status oech-server.service
    systemctl start nginx.service
    systemctl stop firewalld
    iptables -F
    setenforce 0
}

function setup_oech() {
    expect <<-EOF
    set timeout ${TIMEOUT}
    spawn oech
        expect {
            "*Please provide your Compatibility Test ID:"
            {
                send "test\r"
                expect "*Please provide your Product URL:"
                send "test\r"
                expect "*Please provide the Compatibility Test Server (Hostname or Ipaddr):"
                send "${SERVER_IP}\r"
                expect "*Ready to begin testing? (run|edit|quit)"
                send "q\r"
            }
            timeout
            {
                end_user "Connection to execute oech timed out: \$expect_out(buffer)\n ."
                exit ${TIMEOUT_CODE}
            }
        }
EOF
}

function get_exec_number() {
    if [[ ${CARD_TYPE} == "ethernet" || ${CARD_TYPE} == "infiniband" ]]; then
        local device_name=$(get_netdev_name)
    elif  [[ ${CARD_TYPE} == "fc" ]]; then
	local_device_name=$(get_fcdev_pci)
    else
        local device_name=$(get_card_pci)
    fi

    if [[ ${CARD_TYPE} != "nvme" ]]; then
        create_test_config_file ${device_name}
    fi

    local test_id=$(grep ${CARD_TYPE} oech_device.log | grep ${device_name} | awk '{print $1}')
    printf $test_id
}

function exec_oech() {
    local test_id=$1
    if [[ ${test_id} == ${ERROR_CODE} ]]; then
        echo "The test id doesn't exist, test failed."
        exit ${ERROR_CODE}
    fi

    if [[ ${CARD_TYPE} == "ethernet" || ${CARD_TYPE} == "infiniband" ]]; then
        exec_oech_for_nic $test_id
    else
        exec_oech_for_normal $test_id
    fi
}

function exec_oech_for_normal() {
    local test_id=$1
    expect <<-EOF
    set timeout ${TIMEOUT}
    spawn oech
        expect {
            "*Ready to begin testing? (run|edit|quit)"
            {
                send "e\r"
                expect "*Selection (<number>|all|none|quit|run):"
                send "n\n"
                expect "*Selection (<number>|all|none|quit|run):"
                send "${test_id}\n"
                expect "*Selection (<number>|all|none|quit|run):"
                send "r\n"
                expect "*Do you want to submit last result? (y|n)"
                send "y\n"
                expect "*Ready to begin testing? (run|edit|quit)"
                send "q\r"
            }
            timeout
            {
                end_user "Connection to execute oech timed out: \$expect_out(buffer)\n ."
                exit ${TIMEOUT_CODE}
            }
        }
EOF
}

function exec_oech_for_nic() {
    local test_id=$1
    expect <<-EOF
    set timeout ${TIMEOUT}
    spawn oech
        expect {
            "*Ready to begin testing? (run|edit|quit)"
            {
                send "e\r"
                expect "*Selection (<number>|all|none|quit|run):"
                send "n\n"
                expect "*Selection (<number>|all|none|quit|run):"
                send "${test_id}\n"
                expect "*Selection (<number>|all|none|quit|run):"
                send "r\n"
                expect "Are you sure to configure*"
                send "y\n"
                expect "Are you sure to configure*"
                send "y\n"
                expect "*Do you want to submit last result? (y|n)"
                send "y\n"
                expect "*Ready to begin testing? (run|edit|quit)"
                send "q\r"
            }
            timeout
            {
                end_user "Connection to execute oech timed out: \$expect_out(buffer)\n ."
                exit ${TIMEOUT_CODE}
            }
        }
EOF
}

# Get raid/gpu/keycard pci id
function get_card_pci() {
    local card_ids=${CARD_IDS}
    local card_type=${CARD_TYPE}
    local vendorID=$(echo $card_ids | cut -d '-' -f 1)
    local deviceID=$(echo $card_ids | cut -d '-' -f 2)
    local svID=$(echo $card_ids | cut -d '-' -f 3)
    local ssID=$(echo $card_ids | cut -d '-' -f 4)
    if [[ "0000" =~ $svID ]]; then
        svID=""
    fi
    if [[ "0000" =~ $ssID ]]; then
        ssID=""
    fi
    lspci -nvv | grep -A2 ${vendorID}:${deviceID} | grep -q ${svID}:${ssID}
    if [[ $? -ne 0 ]]; then
        echo "The test card cannot find on this machine."
        printf ${ERROR_CODE}
        return 1
    fi

    local card_pci=$(lspci -nvv | grep -A2 ${vendorID}:${deviceID} | grep -B2 ${svID}:${ssID} | head -n 1 | awk '{print $1}')
    if [[ ${card_type} == "nvme" ]]; then
	card_pci=($(ls -l /sys/block | grep ${card_pci} | awk '{print $9}'))
    fi
    printf $card_pci
    return 0
}

# Get fc device name
function get_fcdev_pci() {
    local card_ids=${CARD_IDS}
    local vendorID=$(echo $card_ids | cut -d '-' -f 1)
    local deviceID=$(echo $card_ids | cut -d '-' -f 2)
    local svID=$(echo $card_ids | cut -d '-' -f 3)
    local ssID=$(echo $card_ids | cut -d '-' -f 4)
    if [[ "0000" =~ $svID ]]; then
        svID=""
    fi
    if [[ "0000" =~ $ssID ]]; then
        ssID=""
    fi
    lspci -nvv | grep -A2 ${vendorID}:${deviceID} | grep -q ${svID}:${ssID}
    if [[ $? -ne 0 ]]; then
        echo "The test card cannot find on this machine."
        printf ${ERROR_CODE}
        return ${ERROR_CODE}
    fi
    local card_pcis=$(lspci -nv | grep -A2 ${vendorID}:${deviceID} | grep -B2 ${svID}:${ssID} | awk '$1~/[0-9]/{print $1}')
    for i in ${card_pcis[@]}; do
	local port_names=$(ls -l /sys/class/fc_host | grep $i | awk '{print $9}')
	local port_state=$(cat /sys/class/fc_host/${port_names}/port_state)
	if [[ ${port_state} == "Online" ]]; then
		printf $i
		break
        fi
    done
    return 0
}

# Get nic/ib device name
function get_netdev_name() {
    local card_ids=${CARD_IDS}
    local vendorID=$(echo $card_ids | cut -d '-' -f 1)
    local deviceID=$(echo $card_ids | cut -d '-' -f 2)
    local svID=$(echo $card_ids | cut -d '-' -f 3)
    local ssID=$(echo $card_ids | cut -d '-' -f 4)
    if [[ "0000" =~ $svID ]]; then
        svID=""
    fi
    if [[ "0000" =~ $ssID ]]; then
        ssID=""
    fi
    lspci -nvv | grep -A2 ${vendorID}:${deviceID} | grep -q ${svID}:${ssID}
    if [[ $? -ne 0 ]]; then
        echo "The test card cannot find on this machine."
        printf ${ERROR_CODE}
        return ${ERROR_CODE}
    fi
    local card_pcis=$(lspci -nvv | grep -A2 ${vendorID}:${deviceID} | grep -B2 ${svID}:${ssID} | grep ${vendorID}:${deviceID} | awk '{print $1}')
    local port_names=$(ip link | grep 'state UP' | awk -F: '{print $2}' | awk '{print $1}')
    for i in ${port_names[@]}; do
        local bus_info=$(ethtool -i $i | grep 'bus-info' | awk '{print $2}' | sed 's/.\{5\}//')
        if [[ "${card_pcis[@]}" =~ "${bus_info}" ]]; then
	          printf $i
	          break
        fi
    done
    return 0
}

# Get useful disk to test
function get_useful_disk() {
    local card_pci=$1
    local disks=($(ls -l /sys/block | grep ${card_pci} | awk '{print $9}'))
    for i in $(seq 1 $((${#disks[@]} - 1))); do
        local cur_disk=${disks[$i]}
        df -h | grep $cur_disk
        if [[ $? -ne 0 ]]; then
            printf $cur_disk
            return 0
        fi
    done
    return 1
}

# Create test_config.yaml file to test
function create_test_config_file() {
    local device_name=$1

    mv ${CONFIG_FILE} ${CONFIG_FILE}".bak"

    # Set raid/fc config
    if [[ ${CARD_TYPE} == "raid" || ${CARD_TYPE} == "fc" ]]; then
        local disk=$(get_useful_disk $device_name)
        if [[ $? -eq 1 ]]; then
            echo "There is no useful disk to test $device_name."
            return 1
        fi
        cat > ${CONFIG_FILE} <<EOF
${CARD_TYPE}:
  ${CARD_TYPE}1:
    device: '0000:${device_name}'
    disk: ${disk:-all}
EOF

    # Set ethernet config
    elif [[ ${CARD_TYPE} == "ethernet" ]]; then
        cat > ${CONFIG_FILE} <<EOF
ethernet:
  eth1:
    device: ${device_name}
    if_rdma: N
    client_ip:
    server_ip:
EOF

    # Set infiniband config
    elif [[ ${CARD_TYPE} == "infiniband" ]]; then
        cat > ${CONFIG_FILE} <<EOF
infiniband:
  ib1:
    device: ${device_name}
    client_ip:
    server_ip:
EOF
    fi

    return 0
}

function get_html_report() {
    local machine_name=$(grep "Hardware Info" oech_device.log | cut -d : -f 2 | awk '$1=$1' | sed 's/ /-/g')
    local log_name=$(ls ${LOGDIR} | head -n 1 | sed 's/.tar//g')
    curl http://${SERVER_IP}/results/${machine_name}/test/${log_name} &>${REPORT}
    sed -i "1,4d" ${CARD_NAME}.html
}

# Install outbox driver to test
# This function will realizate by autionmatically hardware driver install tool
function install_driver() {
    local driverlink=$1
    wget $driverlink || return 1
    local driver_rpm=$(ls -t ./ | head -n 1)
    rpm -ivh $driver_rpm || return 1
    if [[ "megaraid_sas" =~ $driver_rpm ]]; then
        return 0
    fi
}

set -x

# Setup oech-server
if [[ ${CARD_TYPE} != "ethernet" ]];then
    setup_oech_server
fi

echo "Start to run oec-hardware test."
# Setup oech information
setup_oech
echo q | oech &>oech_device.log

# Get test suite numbers
test_id=$(get_exec_number)

# Execute oech
exec_oech $test_id
get_html_report

# Upload test results to compass-ci
upload_files -t oec-hardware-log ${LOGDIR}/*
upload_files -t oec-hardware-log ${REPORT}
echo "End to run oec-hardware test."

# write test result
echo q |oech > oech_result.log
test_result=$(sed -n '/'"$test_id"'/p' oech_result.log | awk '{print $3}' | cut -c 8-12)
if [[ $test_result == "FAIL" ]]; then
	test_result=1
else
        test_result=0
fi
echo "test_result" $test_result > $TMP_RESULT_ROOT/oec-hardware
